home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / utils1 / adjramd.arj / AMDISK30.ASM < prev    next >
Assembly Source File  |  1993-09-09  |  21KB  |  673 lines

  1. ; ==== Adjustable Memory Disk Device Driver ====
  2. ;
  3. ; (c) Copyright 1986 by Gary R. Cramblitt
  4. ;
  5. ; v2.2  1 Jul 86  Initial version
  6. ; v2.3 24 Aug 86  Bug.  FAT media byte not updated properly
  7. ; v2.4 29 Aug 86  Sync version # with ADJRAM.C  No other changes.
  8. ; v2.5 30 Aug 86  Add /E (LOTUS/INTEL,Microsoft Expanded Memory) support;
  9. ;          Increase root directory to 128 entries;
  10. ;          Permit maximum size of 2043K.
  11. ;          Get rid of second FAT.
  12. ; v3.0  5 Sep 86  Sync version # with ADJRAM.C.  No other changes.
  13. ;
  14. ; ==== Constant Definition ===================
  15. ;
  16. ; ---- Customizable Definitions -----
  17. ;      If these are changed, the corresponding symbols in adjram.c
  18. ;      must be altered.
  19.  
  20. min_size_K    equ    64        ; minimum 64K ram disk
  21. max_size_K    equ    2043        ; maximum 2043K ram disk
  22. sec_per_blk    equ    64        ; 32K increments
  23. bytes_per_sec    equ    512        ; bytes per sector
  24. sec_per_cl    equ    1        ; sectors per cluster
  25. par_per_sec_lg2    equ    5        ; 16-byte paragraphs per sector
  26.                     ;   log 2.  Must match bytes_per_sec
  27. fats_per_disk    equ    1        ; number of FATS
  28.  
  29. ; ---- Derived quantities ----
  30.  
  31. sec_per_K    equ    1024/bytes_per_sec ; sectors per 1024 bytes
  32. par_per_sec    equ    bytes_per_sec/16   ; 16-byte paragraphs per sector
  33. min_size_sec    equ    min_size_K*sec_per_K ; min size of disk in sectors
  34. max_size_sec    equ    max_size_K*sec_per_K ; max size of disk in sectors
  35. bytes_per_fat    equ    max_size_sec/sec_per_cl*3/2
  36. sec_per_fat    equ    (bytes_per_fat+bytes_per_sec-1)/bytes_per_sec
  37. K_per_blk    equ    sec_per_blk/sec_per_K
  38. em_pag_per_mem_blk equ    K_per_blk/16    ; EM pages per memory block
  39.  
  40. ; ---- Request Header Structure Definitions ----
  41.  
  42. rh_length    equ    0        ; (byte) length field
  43. rh_unit        equ    1 + rh_length    ; (byte) unit field
  44. rh_command    equ    1 + rh_unit    ; (byte) command code
  45. rh_status    equ    1 + rh_command    ; (word) status field
  46. rh_reserved    equ    2 + rh_status    ; (8 bytes)
  47. rh_size        equ    8 + rh_reserved    ; request header size
  48.  
  49. ; ---- Request Header Status values ----
  50.  
  51. s_done        equ    0100h    ; done, no errors
  52. s_busy        equ    0200h    ; busy, no errors
  53.  
  54. e_err        equ    8000h
  55. e_protect    equ    e_err+0h    ; error: write protect
  56. e_unknown_unit    equ    e_err+1h    ; error: unknown unit
  57. e_not_ready    equ    e_err+2h    ; error: not ready
  58. e_command    equ    e_err+3h    ; error: unknown command
  59. e_crc        equ    e_err+4h    ; error: bad CRC
  60. e_bad_length    equ    e_err+5h    ; error: bad structure length
  61. e_seek        equ    e_err+6h    ; error: bad seek
  62. e_media        equ    e_err+7h    ; error: unknown media
  63. e_not_found    equ    e_err+8h    ; error: sector not found
  64. e_paper        equ    e_err+9h    ; error: out of paper
  65. e_write        equ    e_err+ah    ; error: write fault
  66. e_read        equ    e_err+bh    ; error: read fault
  67. e_general    equ    e_err+ch    ; error: general error not listed above
  68.  
  69. ; ---- Non-destructive read parameter block ----
  70.  
  71. rh_read_data    equ    rh_size    ; (byte) non-destructive data
  72.  
  73. ; ---- Input/output parameter block ----
  74.  
  75. rh_media    equ    0 + rh_size        ; (byte) media descriptor
  76. rh_buf_offset    equ    1 + rh_media        ; (word) transfer buffer offset
  77. rh_buf_segment    equ    2 + rh_buf_offset    ; (word) transfer buffer segment
  78. rh_buf_size    equ    2 + rh_buf_segment    ; (word) transfer buffer size
  79. rh_start    equ    2 + rh_buf_size        ; (word) transfer starting sector
  80.  
  81. m_fized        equ    0f8h    ; media: fixed disk
  82.  
  83. m_ss9        equ    0fch    ; media: single sided, 8 sectors/track
  84. m_ds9        equ    0fdh
  85. m_ss8        equ    0feh
  86. m_ds8        equ    0ffh
  87.  
  88. ; ---- Build BPB parameter block ----
  89.                         ; preceeded by media descriptor
  90. rh_bpb        equ    1 + rh_media        ; (dword) bpb buffer address
  91. rh_tbl_offset    equ    4 + rh_bpb        ; (dword) bpb table offset/segment
  92. rh_tbl_segment    equ    2 + rh_tbl_offset
  93.  
  94. ; ---- Media Check parameter block ----
  95.  
  96. rh_check    equ    1 + rh_media        ; (byte) media check result
  97.  
  98. mc_changed    equ    -1            ; media has changed
  99. mc_maybe    equ    0            ; media may have been changed
  100. mc_same        equ    1            ; media has not changed
  101.  
  102. ; ---- Initialize parameter block ----
  103.  
  104. rh_units    equ    0 + rh_size        ; (byte) number of units supported
  105. rh_end_offset    equ    1 + rh_units        ; (word) end address of driver
  106. rh_end_segment    equ    2 + rh_end_offset
  107. rh_bpb_offset    equ    2 + rh_end_segment    ; (word) BPB array address
  108. rh_bpb_segment    equ    2 + rh_bpb_offset
  109.  
  110. ; ---- DOS interrupts ----
  111.  
  112. dosi_dosf    equ    21h        ; DOS function dispatcher
  113.  
  114. ; ---- User Interrupts ----
  115.  
  116. usri_emm    equ    67h        ; Expanded Memory Manager
  117.  
  118. ; ---- DOS interrupt 21 functions ----
  119.  
  120. dosf_outstr    equ    9        ; display string
  121. dosf_seldisk    equ    0eh        ; select disk
  122. dosf_getdisk    equ    19h        ; get current disk
  123.  
  124. ; ---- LOTUS/INTEL/Microsoft Expanded Memory Manager functions ----
  125.  
  126. emm_status    equ    40h        ; get manager status
  127. emm_get_PFseg    equ    41h        ; get page frame segment
  128. emm_get_pages    equ    42h        ; get number of pages
  129. emm_get_handle    equ    43h        ; get handle and allocate memory
  130. emm_map_memory    equ    44h        ; map memory
  131. emm_fre_handle    equ    45h        ; free handle and memory
  132. emm_get_ver    equ    46h        ; get EMM version
  133. emm_sav_map    equ    47h        ; save mapping context
  134. emm_res_map    equ    48h        ; restore mapping context
  135. emm_num_handles    equ    4bh        ; get number of EMM handles
  136. emm_hdl_pages    equ    4ch        ; get pages owned by handle
  137. emm_all_pages    equ    4dh        ; get pages for all handles
  138. emm_pag_map    equ    4eh        ; get or set page map
  139.  
  140. ; ---- Device Driver Header Attribute Definitions ----
  141.  
  142. a_input        equ    0001h        ; standard input device
  143. a_output    equ    0002h        ; standard output device
  144. a_nul        equ    0004h        ; NUL device
  145. a_clock        equ    0008h        ; CLOCK$ device
  146. a_dos        equ    0        ; DOS block device (bit 13)
  147. a_not_dos    equ    2000h        ; non-DOS block device (bit 13)
  148. a_ioctl        equ    4000h        ; IOCTL functions supported
  149. a_block        equ    0        ; block device (bit 15)
  150. a_character    equ    8000h        ; character device (bit 15)
  151.  
  152. ; ==== Device Driver Header Definition ====
  153.  
  154. cseg    segment para public 'CODE'
  155.  
  156. driver    proc far
  157.  
  158.     assume cs:cseg,ds:cseg,es:cseg
  159.  
  160.     dd    -1            ; last driver in chain
  161.     dw    a_block + a_dos        ; driver attribute
  162.     dw    dev_strategy        ; offset to strategy routine
  163.     dw    dev_interrupt        ; offset to interrupt routine
  164.     db    1            ; number of devices or device name
  165.     db    7 dup ( ? )        ; filler for block device
  166.  
  167. ; ==== Device Driver Tables ====
  168. ;
  169. ; ---- BIOS Parameter Block Table and Entries ----
  170.  
  171. bpb_table    dw    bpb        ; one entry for each unit
  172.  
  173. ; ---- Request Header Address set by dev_strategy ----
  174.  
  175. rh_address    dd    1 dup ( ? )        ; request header base address
  176.  
  177. rh_offset    equ    word ptr rh_address
  178. rh_segment    equ    word ptr rh_address + 2
  179.  
  180. ; ---- Request Header Command Dispatch Table ----
  181.  
  182. cmd_table    dw    initialize    ; initialize driver
  183.         dw    media_check    ; media check
  184.         dw    build_bpb    ; build BPB
  185.         dw    ioctl_read    ; IOCTL read
  186.         dw    read        ; normal read
  187.         dw    check_input    ; non-destructive read/status
  188.         dw    input_status    ; input status
  189.         dw    input_flush    ; flush input buffers
  190.         dw    write        ; normal write
  191.         dw    write_verify    ; normal write with read verify
  192.         dw    output_status    ; output status
  193.         dw    output_flush    ; flush output buffer
  194.         dw    ioctl_write    ; IOCTL write
  195.  
  196. ; ==== Common Device Driver Routines ====
  197. ;
  198. ; ---- Device Driver Strategy Routine ----
  199. ;
  200. ; es:bs == request header address
  201.  
  202. dev_strategy    proc    far
  203.         mov    cs:rh_offset,bx
  204.         mov    cs:rh_segment,es
  205.         ret
  206. dev_strategy    endp
  207.  
  208. ; ---- Device Driver Interrupt Routine ----
  209.  
  210. dev_interrupt    proc    far
  211.         push    ax            ; save registers used
  212.         push    bx
  213.         push     cx
  214.         push    dx
  215.         push    di
  216.         push    si
  217.         push    ds
  218.         push    es
  219.          cld                ; clear direction flag
  220.          push    cs            ; setup small memory model
  221.          pop    ds            ; ds := program segment
  222.          les    bx,rh_address        ; es:bs := request header index
  223.          mov    si,es:rh_command[bx]    ; si := request command (byte)
  224.          and    si,0ffh            ; si := request command
  225.          add    si,si            ; si := word table offset
  226.          call    word ptr cmd_table[si]    ; ax := command result
  227.          lds    bx,cs:rh_address    ; ds:bx := request header index
  228.          mov    rh_status[bx],ax    ; update request status
  229.         pop    es            ; restore register
  230.         pop    ds
  231.         pop    si
  232.         pop    di
  233.         pop    dx
  234.         pop    cx
  235.         pop    bx
  236.         pop    ax
  237.         ret
  238.  
  239. dev_interrupt    endp
  240.  
  241. ; **** END OF DEVICE INDEPENDENT PORTION OF DRIVER ****
  242.  
  243. ; ---- Memory Block Table that follows BPB in boot sector ----
  244.  
  245. mem_blk_table_entry    struc
  246. typ        db    ?        ; 0 = normal  1 = Expanded Memory
  247. par        dw    ?        ; paragraph address of block
  248. siz        dw    ?        ; number of sectors in the memory block
  249. hdl        dw    ?        ; EM handle for the block
  250. mem_blk_table_entry    ends
  251.  
  252. nor_flg        equ    0        ; Memory Block is in normal memory
  253. em_flg        equ    1        ; Memory Block is in expanded memory
  254.  
  255. ; ---- Flag indicating whether expanded memory mapping context has been
  256. ;      saved yet or not.  If nonzero, it indicates that the context has
  257. ;      been saved.
  258.  
  259. em_context_flg    db    0        ; 0 = not saved; 1 = context saved
  260. em_context_hdl    dw    ?        ; EM handle underwhich context saved
  261.  
  262. ; ==== Memory Disk Device Driver Code ====
  263. ;
  264. ; ---- Driver support functions (near functions) ----
  265. ;
  266. ; es:bx == request header
  267. ; ds    == cs
  268. ; All other registers are usable.
  269. ;
  270. ; ax := result status
  271. ;
  272. ; ---- Initialize driver ----
  273.  
  274. initialize    proc    near        ; initialize driver
  275.  
  276.     lea    ax,word ptr mdisk_data    ; ax := end of driver
  277.     mov    cl,4            ; cl := paragraph size log2
  278.     shr    ax,cl            ; ax := paragraphs in driver
  279.     mov    dx,cs            ; dx := driver segment
  280.     add    ax,dx            ; ax := memory disk segment
  281.     mov    mem_blk_table.par,ax    ; update for subsequent transfers
  282.  
  283.     mov    ax,cs
  284.     mov    es,ax
  285.     lea    di,word ptr fat1    ; es:di := first FAT
  286.     mov    cx,sec_per_fat*bytes_per_sec ; cx = size
  287.     push    di            ; save first FAT address
  288.     push    es
  289.  
  290.      mov    al,cs:bpb_media        ; al := media byte
  291.      mov    [di],al            ; update FAT media byte
  292.      mov    word ptr 1[di],0ffffh    ; allocate initial sectors
  293.      add    di,3            ; adjust FAT index
  294.      sub    cx,3            ; adjust FAT size
  295.      xor    al,al            ; al := 0
  296.      rep    stosb            ; clear rest of FAT
  297.  
  298.     pop    ds
  299.     pop    si            ; ds:si := first FAT index
  300.  
  301.     if    fats_per_disk - 1    ; assemble if 2 FATS
  302.       lea    di,word ptr fat2    ; es:di := second FAT
  303.           mov    cx,sec_per_fat*bytes_per_sec ; cx := size
  304.       rep    movsb            ; copy first FAT to second FAT
  305.     endif
  306.  
  307.     mov    ax,cs:bpb_root        ; ax := number of directory entries
  308.     mov    cl,5            ; cl := size of entry log2 (32 bytes)
  309.     shl    ax,cl            ; ax := directory size
  310.  
  311.     mov    cx,ax            ; cx := directory size
  312.     xor    al,al            ; al := 0
  313.     rep    stosb            ; zero directory
  314.  
  315.     lds    bx,cs:rh_address    ; ds:bx := request header address
  316.     mov    byte ptr rh_units[bx],1    ; return number of units
  317.     mov    word ptr rh_end_offset[bx],offset mdisk_data
  318.     mov    rh_end_segment[bx],cs    ; Calc end address of disk
  319.     mov    ax,cs:mem_blk_table.siz
  320.     mov    cl,par_per_sec_lg2
  321.     shl    ax,cl
  322.     add    rh_end_segment[bx],ax    ; return ending address of driver
  323.     mov    word ptr rh_bpb_offset[bx],offset bpb_table
  324.     mov    rh_bpb_segment[bx],cs    ; return BPB table address
  325.  
  326.     push    cs
  327.     pop    ds
  328.     mov    ah,dosf_getdisk        ; get current default disk
  329.     int    dosi_dosf
  330.     mov    dl,al            ; select it 
  331.     mov    ah,dosf_seldisk
  332.     int    dosi_dosf        ; DL := number of drives
  333.     add    al,'A'            ; convert to letter
  334.     mov    drive,al        ; store into message
  335.     mov    dx,offset initok
  336.     mov    ah,dosf_outstr
  337.     int    dosi_dosf
  338.     mov    ax,s_done        ; ax := done, no errors
  339.     ret
  340.  
  341. initok    db    10,13,'AMDISK v3.0 (c) Copyright 1986 by Gary Cramblitt'
  342.     db    '-- Initialized as disk '
  343. drive    db    ' '
  344.     db    ':',10,13,'$'
  345.  
  346. initialize    endp
  347.  
  348. ; ---- Media check ----
  349. ;
  350. ; Memory disk is non-removable media, however, the size of the media
  351. ; can be changed.  We check the number of 64K memory blocks allocated,
  352. ; which is located in the boot record.  If it has changed, then the media
  353. ; has changed.
  354.  
  355. media_check    proc    near        ; media check
  356.  
  357.     lds    bx,cs:rh_address    ; ds:bx := request header address
  358.     mov    al,cs:bpb_media        ; Get our media byte
  359.     cmp    al,rh_media[bx]        ; Changed from what DOS has?
  360.     jz    media_same        ; -- Yes
  361.     mov    byte ptr rh_check[bx],mc_changed
  362.     mov    ax,s_done
  363.     ret
  364.  
  365. media_same:
  366.     mov    byte ptr rh_check[bx],mc_same
  367.     mov    ax,s_done        ; ax := function done, no errors
  368.     ret
  369.  
  370. media_check    endp
  371.  
  372. ; ---- Build BPB ----
  373. ;
  374. ; Read boot sector and copy into BPB buffer
  375. ; Adjust request header values
  376.  
  377. build_bpb    proc    near        ; build BPB
  378.  
  379.     mov    al,cs:bpb_media        ; al    := media byte
  380.     lds    bx,cs:rh_address    ; ds:bx    := request header address
  381.     mov    byte ptr rh_media[bx],al
  382.     mov    word ptr rh_tbl_offset[bx],offset bpb
  383.     mov    word ptr rh_tbl_segment[bx],cs
  384.     mov    ax,s_done        ; ax := function done, no errors
  385.      ret
  386.  
  387. build_bpb    endp
  388.  
  389. ; ---- Read from device ----
  390.  
  391. read        proc near        ; normal read
  392.  
  393.     push    es
  394.     pop    ds            ; ds := request header segment
  395.     mov    di,rh_buf_offset[bx]
  396.     mov    ax,di
  397.     and    di,000fh        ; di := buffer offset within paragraph
  398.     mov    cl,4
  399.     shr    ax,cl
  400.     add    ax,rh_buf_segment[bx]    ; ax := paragraph of buffer
  401.     mov    es,ax            ; es:di := normalized buffer address
  402.     mov    dx,rh_buf_size[bx]    ; dx := sectors to read
  403.     mov    ax,rh_start[bx]        ; ax := first sector to read
  404.  
  405.     mov    bx,-(size mem_blk_table_entry)    ; find the memory block which..
  406. find_mem_blk_2_read:                ;  contains the desired sector..
  407.     add    bx,size mem_blk_table        ; by subtracting the # of sectors..
  408.     sub    ax,cs:mem_blk_table.siz[bx] ; in each block.
  409.     jnc    find_mem_blk_2_read
  410.     add    ax,cs:mem_blk_table.siz[bx] ; bx := ptr to memory block table
  411.                         ; ax := sector within the block
  412.  
  413.     push    ax            ; save sector within block
  414.     mov    cl,par_per_sec_lg2    ; paragraphs per sector log 2
  415.     shl    ax,cl            ; ax := paragraph within memory block
  416.  
  417.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  418.     jnz    read_set_par
  419.     call    map_hdl_2_pages            ; - Yes, map EM to log mem
  420.  
  421. read_set_par:
  422.     add    ax,cs:mem_blk_table.par[bx] ; ax := paragraph in phy mem
  423.     mov    ds,ax
  424.     xor    si,si            ; ds:si := address of sector
  425.  
  426.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := end sector
  427.     pop    ax            ; ax := start sector
  428.     sub    cx,ax            ; cx := secs remaining in mem blk
  429.  
  430. read_one_sector:
  431.     or    dx,dx            ; All sectors transfered?
  432.     jz    read_finish        ; -- Yes
  433.     dec    dx
  434.     push    cx            ; save sector count for this blk
  435.     mov    cx,bytes_per_sec    ; 512 bytes per sector
  436.     rep    movsb            ; copy sector to buffer
  437.     pop    cx            ; cx := secs remaining in this blk+1
  438.     mov    ax,ds
  439.     add    ax,par_per_sec        ; 32 paragraphs per sector
  440.     mov    ds,ax
  441.     xor    si,si            ; ds:si := address of next sector
  442.         mov    ax,es            ; advance es to next sector
  443.     add    ax,par_per_sec
  444.     mov    es,ax
  445.     and    di,000fh        ; es:di := normalized transfer address
  446.     loop    read_one_sector        ; if not end of mem blk, do another
  447.     add    bx,size mem_blk_table_entry
  448.  
  449.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  450.     jnz    read_set_par_in_loop
  451.     call    map_hdl_2_pages            ; - Yes, map EM to log mem
  452.  
  453. read_set_par_in_loop:
  454.     mov    ax,cs:mem_blk_table.par[bx]
  455.     mov    ds,ax            ; ds:si := start of new memory block
  456.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := size of blk in sectors
  457.     jmp    read_one_sector
  458.  
  459. read_finish:
  460.     call    restore_em_context    ; If needed, restore em context
  461.     mov    ax,s_done        ; ax := transfer done
  462.     ret
  463.  
  464. read    endp
  465.  
  466. ; ---- Write to device ----
  467.  
  468. write        proc    near        ; normal write
  469.  
  470.     push    es
  471.     pop    ds            ; ds := request header segment
  472.     mov    dx,rh_buf_size[bx]    ; dx := sectors to write
  473.     mov    si,rh_buf_offset[bx]
  474.     mov    ax,si
  475.     and    si,000fh        ; si := buffer offset within paragraph
  476.     mov    cl,4
  477.     shr    ax,cl
  478.     add    ax,rh_buf_segment[bx]    ; ax := paragraph of buffer
  479.     mov    cx,ax
  480.     mov    ax,rh_start[bx]        ; ax := first sector to write
  481.     mov    ds,cx            ; ds:si := normalized buffer address
  482.  
  483.     mov    bx,-(size mem_blk_table_entry)    ; find the memory block which..
  484. find_mem_blk_2_write:                ;   contains the desired sector..
  485.     add    bx,size mem_blk_table_entry ;   by subtracting the # of sectors..
  486.     sub    ax,cs:mem_blk_table.siz[bx] ;  in each block.
  487.     jnc    find_mem_blk_2_write
  488.     add    ax,cs:mem_blk_table.siz[bx]
  489.                     ; bx := ptr to memory block table
  490.                     ; ax := sector within the block
  491.     push    ax            ; save sector within the block
  492.  
  493.     mov    cl,par_per_sec_lg2    ; 32 paragraphs per sector log 2
  494.     shl    ax,cl            ; ax := paragraph within memory block
  495.  
  496.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  497.     jnz    write_set_par
  498.     call    map_hdl_2_pages            ; - Yes, map EM
  499.  
  500. write_set_par:
  501.     add    ax,cs:mem_blk_table.par[bx] ; ax := paragraph in phy mem
  502.     mov    es,ax
  503.     xor    di,di            ; es:di := address of sector
  504.     
  505.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := size of blk in sectors
  506.     pop    ax            ; ax := start sector within blk
  507.     sub    cx,ax            ; cx := secs remaining in mem blk
  508.  
  509. write_one_sector:
  510.     or    dx,dx            ; All sectors transfered?
  511.     jz    write_finish        ; -- Yes
  512.     dec    dx
  513.     push    cx            ; save sector counter
  514.     mov    cx,bytes_per_sec    ; 512 bytes per sector
  515.     rep    movsb            ; copy sector to buffer
  516.     pop    cx            ; cx := secs remaining in blk + 1
  517.     mov    ax,es
  518.     add    ax,par_per_sec        ; 32 paragraphs per sector
  519.     mov    es,ax
  520.     xor    di,di            ; es:di := address of next sector
  521.         mov    ax,ds            ; advance ds to next sector
  522.     add    ax,par_per_sec
  523.     mov    ds,ax
  524.     and    si,000fh        ; ds:si := normalized transfer address
  525.     loop    write_one_sector    ; if not end of block, do another
  526.     add    bx,size mem_blk_table_entry
  527.  
  528.     cmp    cs:mem_blk_table.typ[bx],em_flg ; Expanded Memory?
  529.     jnz    write_set_par_in_loop
  530.     call    map_hdl_2_pages            ; - Yes, map EM
  531.  
  532. write_set_par_in_loop:
  533.     mov    ax,cs:mem_blk_table.par[bx]
  534.     mov    es,ax            ; es:di := start of new memory block
  535.     mov    cx,cs:mem_blk_table.siz[bx] ; cx := size of new blk in secs
  536.     jmp    write_one_sector
  537.  
  538. write_finish:
  539.     call    restore_em_context    ; If needed, restore em context
  540.     mov    ax,s_done        ; ax := transfer done
  541.     ret
  542.  
  543. write    endp
  544.  
  545.  
  546. ; ---- Write and verify ----
  547.  
  548. write_verify    proc    near        ; normal write with read verify
  549.  
  550.     jmp    write            ; assume no errors
  551.  
  552. write_verify    endp
  553.  
  554.  
  555. ; ==== Support Functions ====
  556. ;
  557. ; ----    Map a handle of Expanded Memory to the Memory Block pages
  558.  
  559. ;    ENTRY:    BX = pointer to Memory Block Table entry (in CS)
  560. ;    EXIT:    Memory is mapped and paragraph address updated in entry.
  561. ;        Flag at CS:em_context_flg is set to nonzero to indicate that
  562. ;        expanded memory mapping context has been saved.  The handle
  563. ;        underwhich the context was saved is stored at
  564. ;        CS:em_context_hdl.
  565. ;    USES:    CX
  566.  
  567. map_hdl_2_pages    proc    near
  568.     push    ax
  569.     push    bx
  570.     push    dx
  571.     mov    dx,cs:mem_blk_table.hdl[bx]    ; get handle of mem blk
  572.     cmp    cs:em_context_flg,0        ; em context saved yet?
  573.     jnz    do_map
  574.     mov    ah,emm_sav_map            ; - No, then save it
  575.     int    usri_emm
  576.     mov    cs:em_context_hdl,dx        ; store handle underwhich saved
  577.     mov    cs:em_context_flg,1        ; flag as saved
  578. do_map:
  579.     push    bx
  580.     mov    ah,emm_get_PFseg        ; get page frame segment
  581.     int    usri_emm
  582.     mov    ax,bx
  583.     pop    bx
  584.     mov    cs:mem_blk_table.par[bx],ax    ; store page frame segment
  585.     mov    cx,em_pag_per_mem_blk        ; # of 16K EM pages to map
  586. map_log_2_phy:
  587.     mov    ah,emm_map_memory        ; map memory
  588.     mov    al,cl                ; physical page number
  589.     mov    bx,cx                ; logical page number
  590.     dec    al                ; adjust relative to 0
  591.     dec    bx                ; adjust relative to 0
  592.     int    usri_emm
  593.     loop    map_log_2_phy
  594.     pop    dx
  595.     pop    bx
  596.     pop    ax
  597.     ret
  598. map_hdl_2_pages    endp
  599.  
  600. ; ---- Restore expanded memory context, if needed. ---
  601. ;    USES:    AX,DX
  602.  
  603. restore_em_context    proc    near
  604.     cmp    cs:em_context_flg,0    ; was context saved?
  605.     jz    restore_em_context_xit    ; - No, then just exit
  606.     mov    ah,emm_res_map        ; - Yes, then restore it..
  607.     mov    dx,cs:em_context_hdl    ;   ..using this handle
  608.     int    usri_emm
  609.     mov    cs:em_context_flg,0    ; clear context flag
  610. restore_em_context_xit:
  611.     ret
  612. restore_em_context    endp
  613.  
  614. ; ---- Unimplemented functions ----
  615.  
  616. unimplemented    proc    near
  617.     mov    ax,e_command
  618.     ret
  619. unimplemented    endp
  620.  
  621. ioctl_read    equ    unimplemented    ; IOCTL read
  622. check_input    equ    unimplemented    ; non-destructive read/status
  623. input_status    equ    unimplemented    ; input status
  624. input_flush    equ    unimplemented    ; flush input buffers
  625. output_status    equ    unimplemented    ; output status
  626. output_flush    equ    unimplemented    ; flush output buffers
  627. ioctl_write    equ    unimplemented    ; IOCTL write
  628.  
  629. ; ==== Memory Disk Data Area ====
  630. ;
  631. ; Align to paragraph boundary for easy computation of the sector address
  632.  
  633. if (( $ - driver) mod 16 )
  634.     org    ( $ - driver) + (16 - (( $- driver) mod 16 ))
  635. endif
  636.  
  637. mdisk_data    equ    $        ; memory disk starts here
  638.  
  639. ; ---- Boot record for initialization ----
  640.  
  641. boot_record    db    3 dup ( 0 )    ; non-bootable (no jump instruction )
  642.         db    'AMDISK  '    ; identification
  643.  
  644. bpb:                    ; BIOS Parameter Block
  645. bytes_in_sector    dw    bytes_per_sec    ; bytes/sector
  646. bpb_sec_per_cl    db    sec_per_cl    ; sectors/cluster
  647. bpb_reserved    dw    1        ; reserved sectors
  648. bpb_fats    db    fats_per_disk    ; number of FAT's
  649. bpb_root    dw    128        ; directory entries in root
  650. bpb_total    dw    min_size_sec    ; total number of sectors
  651. bpb_media    db    1        ; media type byte ...
  652. mem_blk_cnt    equ    bpb_media    ; ...is used for number of mem blocks
  653. bpb_fat_size    dw    sec_per_fat    ; sectors/FAT
  654.  
  655.         dw    1        ; sectors/track
  656.         dw    1        ; number of heads
  657.         dw    0        ; hidden sectors
  658.  
  659. mem_blk_table    mem_blk_table_entry <nor_flg,,min_size_sec,0>  ; memory block table
  660. end_mem_blk_table equ    $+(size mem_blk_table)*(max_size_sec/sec_per_blk)
  661.  
  662. fat1        equ    boot_record + bytes_per_sec
  663. fat2        equ    fat1 + (bytes_per_sec*sec_per_fat)
  664. root_dir    equ    fat1+(fats_per_disk*sec_per_fat*bytes_per_sec)
  665. first_data_sec    equ    root_dir + (64*32)
  666.  
  667. ; ==== End of Memory Disk Device Driver ====
  668.  
  669. driver        endp
  670. cseg        ends
  671.         end
  672.  
  673.